<?php

namespace App\Listeners;

use Monolog\Handler\StreamHandler;
use Monolog\Logger;

class QueryListener
{
    protected $log;

    /**
     * QueryListener constructor.
     *
     * @throws \Exception
     */
    public function __construct()
    {
        $this->log = new Logger('mysql');

        // 创建mysql文件夹
        $dir_path = dirname(dirname(__DIR__)) . '/storage/logs/' . $this->log->getName();
        if (!is_dir($dir_path)) mkdir($dir_path, 0755);

        // 年月的日志目录
        $year_path = $dir_path . '/' . date('Y');
        if (!is_dir($year_path)) mkdir($year_path, 0755);

        $month_path = $year_path . '/' . date('m');
        if (!is_dir($month_path)) mkdir($month_path, 0755);

        $log_path  = storage_path('logs/' . $this->log->getName() . '/' . date('Y') . '/' . date('m') . '/' . date('d') . '.log');
        if (!file_exists($log_path)) {
            fopen($log_path, "w");
        }

        $this->log->pushHandler(new StreamHandler($log_path, Logger::DEBUG));
    }

    /**
     * Handle the event.
     *
     * @param object $event
     *
     * @return void
     */
    public function handle($event): void
    {
        if (env('APP_DEBUG') == true) {
            $sql = str_replace("?", "'?'", $event->sql);
            if ($event->bindings){
                $log = $this->interpolateQuery($event->sql, $event->bindings);
//                $log = vsprintf($sql, $event->bindings)??$sql;
            }else{
                $log = $sql;
            }
            $this->log->addRecord(Logger::DEBUG, '[' . $event->time . '] | ' . $log . ' |');
        }
    }
    /**
     * 将参数插入到 SQL 查询字符串中，用于日志记录。
     * @param  string  $query
     * @param  array  $bindings
     * @return string
     */
    protected function interpolateQuery($query, $bindings)
    {
        $result = $query;
        // 遍历绑定参数，替换查询中的占位符（?）
        foreach ($bindings as $key => $value) {
            // 根据参数类型进行不同的处理
//            if (is_string($value)) {
//                $value = "'" . $this->escapeString($value) . "'";
//            } elseif (is_null($value)) {
//                $value = 'NULL';
//            }
            // 替换第一个出现的占位符（?）
            $result = preg_replace('/\?/', $value, $result, 1);
        }
        return $result;
    }
    /**
     * 转义字符串中的特殊字符，防止 SQL 注入。
     * @param  string  $value
     * @return string
     */
    protected function escapeString($value)
    {
        // 这里你可以使用数据库连接提供的转义方法，或者简单地使用 addslashes
        // 注意：在实际应用中，应该避免直接使用 addslashes，因为它不是万无一失的
        // 这里仅作为示例
        return addslashes($value);
    }
}
